Skip to content

basic chapter list for audiobook items - #8112

Closed
dkanada wants to merge 2 commits into
jellyfin:masterfrom
dkanada:book-chapters
Closed

basic chapter list for audiobook items#8112
dkanada wants to merge 2 commits into
jellyfin:masterfrom
dkanada:book-chapters

Conversation

@dkanada

@dkanada dkanada commented Jun 30, 2026

Copy link
Copy Markdown
Member

Changes

Provides a very rudimentary chapter view for audiobooks now that jellyfin/jellyfin#16518 has been merged. I had grand plans for progress tracking but the itemDetails page isn't on React yet, so the required modifications were a pain.

I also tried a list.js replacement but that entire component probably needs to be rearchitected. Didn't want to tackle that at the same time.

Issues

None

Code Assistance

None

@dkanada
dkanada requested a review from a team as a code owner June 30, 2026 11:43
@jellyfin-bot

jellyfin-bot commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Cloudflare Pages deployment

Latest commit eb877f8
Status ✅ Deployed!
Preview URL https://32c34834.jellyfin-web.pages.dev
Type 🔀 Preview

View build logs

@jordanmichaelrushing

Copy link
Copy Markdown
Contributor

Just so you're aware, I also made a chapters PR (amongst a bunch of things). To your specific change, I did a similar fix but ended up using the scenes section, but only on multi file audiobooks. To me this looks fine, if this gets merged in before mine I'll probably update mine to make sure multi-file uses your new section. Personally I have no preference either. Nice work

@jellyfin-bot jellyfin-bot added the merge conflict Conflicts prevent merging label Jun 30, 2026
@jellyfin-bot

This comment has been minimized.

@jellyfin-bot jellyfin-bot added the stale No activity for an extended length of time label Jul 1, 2026
@jellyfin-bot jellyfin-bot removed the merge conflict Conflicts prevent merging label Jul 2, 2026
@thornbill thornbill removed the stale No activity for an extended length of time label Jul 2, 2026
@jordanmichaelrushing

jordanmichaelrushing commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Played around with this and I believe there's a slight problem. When you're on the item page and edit the metadata it reloads and gives an error in the JS console and the section gets removed.

HTML wise all children of #childrenCollapsible .itemsContainer get removed, but both #childrenCollapsible & .itemsContainer do not get the hide class added, so it's not a can of being hidden, it's the html gets wiped out and not re-added (I assume because of the JS error).

image

@jordanmichaelrushing

Copy link
Copy Markdown
Contributor

Ok I figured out the issue:
renderChapters reuses same .itemsContainer on every metadata refetch, without unmounting prior root first. Two React roots fight over same node: removeChild crash. Also no else branch to add hide class back when chapters missing.

3 solutions:

  1. Create a new dedicated section that isn't reusing another one (and follows the same structure as option 2 below)
  2. Follow roughly the suggestion below (notice I'm setting hide when audiobook but no chapters & I'm setting the unmount instead of on element I'm setting it on the new renderTarget AND more importantly I'm setting innerHTML = '' which is helping to clear it out:
 function renderChapters(page, instance, item) {
     if (item.Type !== BaseItemKind.AudioBook) return;
     const container = page.querySelector('#childrenCollapsible');
     const element = container.querySelector('.itemsContainer');

     if (!item.Chapters?.length) {
        container.classList.add('hide');
        return;
    }

    element.innerHTML = '';
    const renderTarget = document.createElement('div');
    element.appendChild(renderTarget);

    instance._unmount.push(renderComponent(ItemDetailsChapterList, { item }, renderTarget));
    container.classList.remove('hide');
    element.classList.add('vertical-list');
}
  1. (My preferred): The reason I used the renderScenes function in my PR is that it already calls item.Chapters. The only reason this doesn't currently work for single file audiobooks is because the embedded chapters don't have images. So if you simply change:
if (chapters.length && !chapters[0].ImageTag) {

to

if (chapters.length && !chapters[0].ImageTag && item.Type !== BaseItemKind.AudioBook) {

it automagically works. The only caveat is the look isn't the prettiest. To fix that go to chaptercardbuilder.js:

[line 71]: function getImgUrl({ Id, ImageTags }, { ImageTag }, index, maxWidth, apiClient) {
[lines 82-89]: 
    if (ImageTags?.Primary) {
        return apiClient.getScaledImageUrl(Id, {
            maxWidth: maxWidth,
            tag: ImageTags.Primary,
            type: 'Primary'
        });
    }

I know, "basic chapter list for audiobook items". That's why there's the other 2 options. That being said, this is IMHO still a small change and makes it look better. Options 1 & 2 look like this:
image

Option 3 without the image fix looks like this:
image

Option 3 with the image fix looks like this:
image

@sevenrats

Copy link
Copy Markdown
Member

#8207

@dkanada

dkanada commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@jordanmichaelrushing thanks for the analysis - pushed a small fix. @sevenrats your pull request is objectively more useful since it properly tracks playback state, but I'm going to try and get this into 12.0 before a released is tagged.

@dkanada

dkanada commented Jul 21, 2026

Copy link
Copy Markdown
Member Author

@sevenrats I forgot to mention the reason: your PR has ballooned to 3000 LOC so there's no chance for a 12.0 merge. We can shift gears once the new release comes out.

@sevenrats

Copy link
Copy Markdown
Member

@sevenrats I forgot to mention the reason: your PR has ballooned to 3000 LOC so there's no chance for a 12.0 merge. We can shift gears once the new release comes out.

yeah that makes sense. if this direction changes please let me know asap because my PR is actually 1 of a series of PR's so if we are going to change direction I want as much notice as possible to try and preserve improvements that are downstream of my chapters PR.

@sonarqubecloud

Copy link
Copy Markdown

@dkanada dkanada closed this Jul 30, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in Jellyfin 12.0 Jul 30, 2026
@dkanada
dkanada deleted the book-chapters branch July 30, 2026 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants